﻿#!/usr/bin/env python
# -*- coding: utf-8 -*-

# THIS FILE AIMS TO GENERATE INVOICE FILES
# IT CAN RUN ON ONLY WINDOWS

import wx
import win32com.client
import os, shutil
import time
import csv
import pickle

INVOICE_NO = 0
MONTH = 1
KO_NAME = 2
EN_NAME = 3
S_EN_NAME = 4
REQ_KO_DATE = 5
REQ_EN_DATE = 6
DUR_KO_DATE = 7
DUR_EN_DATE = 8
CLASS_COUNT = 9
PRICE_UNIT = 10
TOTAL_PRICE = 11
KR_TOTAL_PRICE = 12
COODI = 13

YEAR = '11'
DEFAULT_LOCATION = r'c:\invoice\template'

def _kr(str):
    return unicode(str).encode('euc-kr')

class InvoiceGenerater(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, 'Invoice Generater',
                size=(620, 450))
        self.panel = wx.Panel(self, -1)
        self.panel.SetBackgroundColour('Block')
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)

        self.init_menu()
        self.init_config()
        self.pref = {}
        self.load()

    def init_menu(self):
        menuBar = wx.MenuBar()
        menu = (('&File',
                    ('&Open', 'Open in status bar', self.OnOpen),
                    ('&Quit', 'Quit', self.OnCloseWindow)),
                ('&Edit',
                    ('&Options...', 'DisplayOptions', self.OnOptions)))
        for m in menu:
            menuLabel = m[0]
            menuItems = m[1:]
            menuBar.Append(self._createMenu(menuItems), menuLabel)
        self.SetMenuBar(menuBar)

    def _createMenu(self, menuData):
        menu = wx.Menu()
        for eachLabel, eachStatus, eachHandler in menuData:
            if not eachLabel:
                menu.AppendSeparator()
                continue
            menuItem = menu.Append(-1, eachLabel, eachStatus)
            self.Bind(wx.EVT_MENU, eachHandler, menuItem)
        return menu

    def init_config(self):
        static = wx.StaticText(self.panel, wx.NewId(), 'Source File Location', (10, 10))
        static.SetBackgroundColour('Block')
        self.sourceTxt = wx.TextCtrl(self.panel, wx.NewId(), '', size=(350, -1), pos=(125, 10))
        self.sourceTxt.SetValue(os.getcwd())
        button = wx.Button(self.panel, -1, 'Find', pos=(500, 10))
        self.Bind(wx.EVT_BUTTON, self.OnSourceFind, button)

        static = wx.StaticText(self.panel, wx.NewId(), 'Target File Location', pos=(10, 40))
        static.SetBackgroundColour('Block')
        self.targetTxt = wx.TextCtrl(self.panel, wx.NewId(), '', size=(350, -1), pos=(125, 40))
        self.targetTxt.SetValue(os.getcwd())
        button = wx.Button(self.panel, -1, 'Find', pos=(500, 40))
        self.Bind(wx.EVT_BUTTON, self.OnTargetFind, button)

        static = wx.StaticText(self.panel, wx.NewId(), 'Log', pos=(10, 70))
        static.SetBackgroundColour('Block')
        self.logTxt = wx.TextCtrl(self.panel, wx.NewId(), '', style=wx.TE_MULTILINE, size=(350, 300), pos=(125, 70))

        button = wx.Button(self.panel, -1, 'Generate', pos=(500, 70))
        self.Bind(wx.EVT_BUTTON, self.OnGenerate, button)

    def load(self):
        f = open(r'c:/invoice/pref.ini')
        self.pref = pickle.load(f)
        self.sourceTxt.SetValue(self.pref.get('source', os.getcwd()))
        self.targetTxt.SetValue(self.pref.get('target', os.getcwd()))

    def save(self):
        f = open(r'c:/invoice/pref.ini', 'w')
        pickle.dump(self.pref, f)
        f.close()

    # event handlers
    def OnSourceFind(self, event):
        self.OpenFile(event)

    def OnTargetFind(self, event):
        pwd = self.pref.get('target', os.getcwd())
        dialog = wx.DirDialog(None, 'Choose a directory:', pwd, style=wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON)
        if dialog.ShowModal() == wx.ID_OK:
            self.pref['target'] = dialog.GetPath()
            self.targetTxt.SetValue(dialog.GetPath())
        dialog.Destroy()

    def OnOpen(self, event):
        self.OpenFile(event)

    def OpenFile(self, event):
        wildcard = 'CSV file (*.csv)|*.csv|All files (*.*)|*.*'
        pwd = self.pref.get('source', os.getcwd())
        dialog = wx.FileDialog(None, 'Choose a file', pwd, '', wildcard, wx.OPEN)
        if dialog.ShowModal() == wx.ID_OK:
            self.pref['source'] = dialog.GetPath()
            self.sourceTxt.SetValue(dialog.GetPath())

        dialog.Destroy()

    def OnGenerate(self, event):
        if not self.sourceTxt.GetValue():
            wx.MessageBox('Choose CSV File!', 'Error')
            return False
        if not self.targetTxt.GetValue():
            wx.MessageBox('Choose location', 'Error')
            return False
        self.read_cvs()

    def OnOptions(self, event):
        pass

    def OnCloseWindow(self, event):
        self.save()
        self.Destroy()

    # logic
    def put_en_invoice(self, row, target_file):
        try :
            xl = win32com.client.Dispatch('Excel.Application')
            wb = xl.Workbooks.Open(target_file)
            sh = wb.worksheets(1)
            sh.Cells(3, 3).Value = 'Invoice No: emci-' + row[INVOICE_NO] + row[S_EN_NAME] + YEAR
            sh.Cells(4, 3).Value = 'Invoice Date: ' + row[REQ_EN_DATE ]
            sh.Cells(18, 1).Value = row[EN_NAME]
            sh.Cells(27, 1).Value = row[DUR_EN_DATE]
            sh.Cells(27, 2).Value = row[PRICE_UNIT]
            sh.Cells(27, 3).Value = row[CLASS_COUNT]
            sh.Cells(27, 4).Value = row[TOTAL_PRICE]
            wb.Save()
            wb.Close()
        except:
            self.logTxt.AppendText('Error put_en_invoic.\n')
            wb.Save()
            wb.Close()

    def put_kn_invoice(self, row, target_file):
        try :
            xl = win32com.client.Dispatch('Excel.Application')
            wb = xl.Workbooks.Open(target_file)
            sh = wb.worksheets(1)
            sh.Cells(3, 3).Value = u'발행번호: emci-' + row[INVOICE_NO] + row[S_EN_NAME] + YEAR
            sh.Cells(4, 3).Value = _kr(u'발행일: ') + row[REQ_KO_DATE]
            sh.Cells(18, 1).Value = row[KO_NAME]
            sh.Cells(27, 1).Value = row[DUR_KO_DATE]
            sh.Cells(27, 2).Value = row[PRICE_UNIT]
            sh.Cells(27, 3).Value = row[CLASS_COUNT]
            sh.Cells(27, 4).Value = row[TOTAL_PRICE]
            wb.Save()
            wb.Close()
        except:
            self.logTxt.AppendText('Error put_kn_invoice.\n')
            wb.Save()
            wb.Close()

    def put_product(self, row, target_file):
        try :
            xl = win32com.client.Dispatch('Excel.Application')
            wb = xl.Workbooks.Open(target_file)
            sh = wb.worksheets(1)
            sh.Cells(4, 3).Value = row[REQ_KO_DATE]
            sh.Cells(5, 1).Value = row[KO_NAME]
            sh.Cells(8, 7).Value = row[KR_TOTAL_PRICE]
            sh.Cells(8, 19).Value = row[TOTAL_PRICE]
            sh.Cells(11, 9).Value = row[CLASS_COUNT]
            sh.Cells(11, 11).Value = row[PRICE_UNIT]
            sh.Cells(11, 15).Value = row[TOTAL_PRICE]
            sh.Cells(27, 20).Value = row[COODI]
            wb.Save()
            wb.Close()
        except:
            self.logTxt.AppendText('Error put_product.\n')
            wb.Save()
            wb.Close()

    def put_estimate(self, row, target_file):
        try :
            xl = win32com.client.Dispatch('Excel.Application')
            wb = xl.Workbooks.Open(target_file)
            sh = wb.worksheets(1)
            sh.Cells(4, 3).Value = row[REQ_KO_DATE]
            sh.Cells(5, 1).Value = row[KO_NAME]
            sh.Cells(8, 7).Value = row[KR_TOTAL_PRICE]
            sh.Cells(8, 19).Value = row[TOTAL_PRICE]
            sh.Cells(11, 9).Value = row[CLASS_COUNT]
            sh.Cells(11, 11).Value = row[PRICE_UNIT]
            sh.Cells(11, 15).Value = row[TOTAL_PRICE]
            sh.Cells(27, 20).Value = row[COODI]
            wb.Save()
            wb.Close()
        except:
            self.logTxt.AppendText('Error put_estimate.\n')
            wb.Save()
            wb.Close()

    def make_file(self, row):
        FILE_NAMES = [
            'estimate.xls',
            'product.xls',
            'Tax_Invoice_en.xls',
            'Tax_Invoice_ko.xls',
            ]
        NEW_FILE_NAMES = [
            u'견적서.xls',
            u'납품서.xls',
            u'영문청구서.xls',
            u'국문청구서.xls',
            ]
        functions = [
            self.put_estimate,
            self.put_product,
            self.put_en_invoice,
            self.put_kn_invoice,
            ]
        name = row[1] + '_' + row[2]
        target_dir = os.path.join(str(self.targetTxt.GetValue()), name)

        if os.path.isdir(target_dir) == False:
            os.mkdir(target_dir)
            for i, file_name in enumerate(FILE_NAMES):
                source_file = os.path.join(DEFAULT_LOCATION, file_name)
                target_file = os.path.join(target_dir, row[2] + '_' + _kr(NEW_FILE_NAMES[i]))
                self.logTxt.AppendText(target_file + '\n')
                shutil.copyfile(source_file, target_file)
                #time.sleep(1)
                functions[i](row, target_file)
            cmd = 'ConvertXLS /S"' + target_dir + '\\*.xls" ' + '/T"' + target_dir + '\\*.pdf" /C-1'
            pdf_convertor = open(target_dir + '\\converting_pdf.bat', 'w')
            pdf_convertor.write(cmd)
            pdf_convertor.close()
            self.logTxt.AppendText('Finished.\n')
            wx.MessageBox('Finished', 'Info')
        else:
            wx.MessageBox('Exist the same files', 'Error')
            self.logTxt.AppendText('Exist the same files.\n')
            return False

    def read_cvs(self):
        try :
            infile = self.sourceTxt.GetValue()
            for row in csv.reader(open(infile)):
                self.make_file(row)
        except:
            wx.MessageBox('Exist the same files', 'Error')
            self.logTxt.AppendText('Error Opening invoice file.\n')
            return False

if __name__ == '__main__':
    app = wx.PySimpleApp()
    frame = InvoiceGenerater(parent=None, id=-1)
    frame.Show()
    app.MainLoop()

